#include "DID.h"

#include "Build_Time.h"
#include "Config.h"
#include "debug.h"
#include "Dev_manage.h"
#include "eeprom.h"
#include "uds_service.h"
#include "Version.h"

#include <string.h>

uint8_t Get_current_session(uint8_t *dat)
{
    *dat = get_current_session();
    return 1;
}

uint8_t Get_Boot_Version(uint8_t *dat)
{
    *dat++ = 0;
    *dat++ = 0;
    *dat++ = 0;
    return 3;
}
uint8_t Get_APP_Version(uint8_t *dat)
{
    *dat++ = SOFT_VER_X;
    *dat++ = SOFT_VER_Y;
    *dat++ = SOFT_VER_Z;
    return 3;
}

uint8_t Get_HardWare_Version(uint8_t *dat)
{
    *dat++ = HARD_VERSION[0];
    *dat++ = HARD_VERSION[1];
    *dat++ = HARD_VERSION[2];
    return 3;
}

uint8_t Get_BuildTime(uint8_t *dat)
{
    *dat++ = UINT8to2BCD(BUILD_YEAR_L);
    *dat++ = UINT8to2BCD(BUILD_MONTH);
    *dat++ = UINT8to2BCD(BUILD_DAY);
    *dat++ = UINT8to2BCD(BUILD_HOUR);
    *dat++ = UINT8to2BCD(BUILD_MINUTE);
    *dat++ = UINT8to2BCD(BUILD_SECOND);
    return 6;
}

// 添加适配器函数
uint16_t Get_comp_config(uint8_t *p_data)
{
    uint8_t flash_data[COMP_CONFIG_INFO_COUNT] = { 0 };

    // 直接从Flash读取原始配置数据
    if (VME2P_Read(VM_INDEX_COMP_CONFIG, flash_data, COMP_CONFIG_INFO_COUNT) == COMP_CONFIG_INFO_COUNT) {
        // 检查数据有效性（可选）
        if (flash_data[COMP_CONFIG_INFO_COUNT - 1] == COMP_CONFIG_WRITE_FLAG) {
            memcpy(p_data, flash_data, COMP_CONFIG_INFO_COUNT);
            return COMP_CONFIG_INFO_COUNT;
        }
    }

    return 0; // 读取失败或数据无效
}

uint16_t get_whether_to_encrypt(uint8_t *p_data)
{
    uint8_t flash_data;

    if (VME2P_Read(VM_INDEX_DATA_ENCRYPT, &flash_data, 1) == 1) {
        *p_data = flash_data;
        return 1;
    }

    *p_data = 0;
    return 0;
}

#if 0
uint8_t Get_Bat_Voltage_BCD(uint8_t *dat)
{

    uint16_t vol = Get_Bat_Voltage();
    *dat++       = Syslib_U8ToBCD(vol/1000);
    *dat++       = Syslib_U8ToBCD(vol %1000/10);
    return 2;
}
#endif
typedef uint16_t (*Read_handle)(uint8_t *p); // 定义函数指针

typedef struct
{
    uint16_t did;                        // DID
    bool     Read;                       // 允许读
    bool     Write;                      // 允许写
    uint8_t *ram_addr;                   // RAM地址
    uint16_t Flash_addr;                 // Flash地址,掉电保存
    uint8_t  len;                        // 数据实际长度
    uint16_t (*Read_handle)(uint8_t *p); // 特殊读取函数,实时数据，未在RAM里存储的，或需编码的
} DID_ADDR_RW_handle;

DID_ADDR_RW_handle DID_table[] = {
    // DID    read  write  ram, flash,len,handle
    { 0XF186, true, false, NULL, 0, 1, Get_current_session },  // 诊断会话状态
    { 0XFD00, true, false, NULL, 0, 3, Get_Boot_Version },     // Boot版本
    { 0XFD01, true, false, NULL, 0, 3, Get_APP_Version },      // APP版本
    { 0XFD02, true, false, NULL, 0, 3, Get_HardWare_Version }, // 硬件版本
    //{ 0XFD03, true, false, NULL, 0, 3, Get_Bat_Voltage_BCD }, // 工作电压
    { 0XFD04, true, true, NULL, VM_INDEX_DEV_ID, 2, Dev_ReadNodeID }, // 节点ID
    { 0XFD05, true, false, NULL, 0, 6, Get_BuildTime },               // 构建日期
    { 0XFD06, true, true, NULL, VM_INDEX_DATA_FORMAT, 1, NULL },      // 传感器输出格式
    /* 8Byty [点位数] [起始点位号] [湿补点对数] [湿补点1] [参考点1] [湿补点2] [参考点2] [FLAG] */
    { 0XFD07, true, true, NULL, VM_INDEX_COMP_CONFIG, COMP_CONFIG_INFO_COUNT,
      Get_comp_config },                                                            // 湿补点配置
    { 0XFD08, true, true, NULL, VM_INDEX_DATA_ENCRYPT, 1, get_whether_to_encrypt }, // 数据加密
    // FD10 ~ FD1D 传感器节点校准数据，【注意】
};

// FD11-FD1D

/**
 * @brief 通过did值读取数据
 *
 * @param did       要读取的数据标识符
 * @param p_data    用于存储读取数据的缓冲区指针
 * @return int16_t
 */
int16_t ReadDid_Port(uint16_t did, uint8_t *p_data)
{
    uint16_t index = 0;
    uint16_t ret;

    uint16_t ret_val      = 0;
    uint8_t  Read_flag    = 0;
    uint32_t Read_address = 0;
    uint16_t Read_len     = 0;

    /* 特殊DID处理 */
    if ((did >= 0xFD10) && (did <= 0XFD1D)) {
        // 点位校准数据
        Read_flag    = 1;
        Read_address = did - 0XFD10 + VM_INDEX_POINT0;
        Read_len     = 110;
    }
    /* 常规DID处理 */
    else {
        for (index = 0; index < (sizeof(DID_table) / sizeof(DID_table[0])); index++) {
            if (did == DID_table[index].did) {
                // 找到对应did
                if (false == (DID_table[index].Read)) {
                    return -NRC_REQUEST_OUT_OF_RANGE;
                }

                Read_flag    = 1;
                Read_address = DID_table[index].Flash_addr;
                Read_len     = DID_table[index].len;

                if (DID_table[index].Read_handle != NULL) { // 特殊读取函数
                    ret = (DID_table[index].Read_handle)(p_data);
                    return ret;
                }
            }
        }
    }

    if (Read_flag == 0) {
        return -NRC_REQUEST_OUT_OF_RANGE;
    }

    ret_val = VME2P_Read(Read_address, (p_data), Read_len);
    if (ret_val != Read_len) {
        LOG("ret= %d,Read_len=%d\r\n", ret_val, Read_len);
        return -NRC_GENERAL_PROGRAMMING_FAILURE;
    }
    return ret_val;
}

// 通过did值写入数据
int16_t WriteDid_Port(uint16_t did, const uint8_t *p_data, uint16_t len)
{
    uint16_t index         = 0;
    uint16_t ret_val       = 0;
    uint8_t  Write_flag    = 0;
    uint32_t Write_address = 0;
    uint16_t Write_len     = 0;

    LOG("%s:did=0x %x  \r\n", __FUNCTION__, did);
    /*
        //TODO:安全访问确认是否需要
        if (Diag.SecurityAccessStatusLevel1 != SECURITY_ACCESS_UNLOCK)
        {     //安全访问LV1未解锁
            return -NRC_SECURITY_ACCESS_DENIED;
        }  */

    if ((did >= 0xFD10) && (did <= 0XFD1D)) {
        // 点位校准数据
        Write_flag    = 1;
        Write_address = did - 0XFD10 + VM_INDEX_POINT0;
        Write_len     = 110;
    }
    else {
        for (index = 0; index < (sizeof(DID_table) / sizeof(DID_table[0])); index++) {
            if (did == DID_table[index].did) {
                // 找到对应did
                if (false == (DID_table[index].Write)) {
                    break;
                }

                Write_flag    = 1;
                Write_address = DID_table[index].Flash_addr;
                Write_len     = DID_table[index].len;
            }
        }
    }

    if (Write_flag == 0) {
        // 不支持写操作
        return -NRC_REQUEST_OUT_OF_RANGE;
    }

    // 长度不匹配
    if (len != Write_len) {
        return -NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT;
    }

    // TODO
    ret_val = VME2P_Write(Write_address, (p_data), len);
    if (ret_val != len) {
        return -NRC_GENERAL_PROGRAMMING_FAILURE;
    }

    return ret_val;
}
